package br.usp.icmc.biomac.client.view.lixo;

import java.util.Map;

import br.usp.icmc.biomac.client.Resources.GlobalResources;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.Widget;

/**
 *
 * @author amsnyder
 */
public class DicomResultGridImpl extends Composite implements DicomResultGrid{
    interface DicomGridViewUiBinder extends UiBinder<Widget, DicomResultGridImpl> {}
    private static DicomGridViewUiBinder uiBinder = GWT.create(DicomGridViewUiBinder.class);

//    private static EPadLogger log = EPadLogger.getLogger();

    @UiField Grid dicomTable;

	private Presenter presenter;

    static {
//        RESOURCE.dicomSearch().ensureInjected();
    }
    public static final GlobalResources RESOURCE = GWT
	.create(GlobalResources.class);


    //attribute names used in this table.
    private static final String ATTR_DICOM_TYPE = "dicomtype";
    private static final String ATTR_STUDY_ID = "studyid";
    private static final String ATTR_SERIES_ID = "seriesid";
    private static final String ATTR_THUMBNAIL = "thumbnail";
    private static final String ATTR_SERIES_DESC = "seriesdesc";
    private static final String ATTR_NUM_IMAGES = "numimages";

    //valid dicomtype attribute values.
    private static final String DT_STUDY = "study";
    private static final String DT_SERIES = "series";

    private static int NUM_COLUMNS = 6; //number of columns in table.

    public DicomResultGridImpl() {
        initWidget(uiBinder.createAndBindUi(this));

        dicomTable.resize(7,6);
        buildBlankResultTable();

        //Add a click handler to column 0.
        dicomTable.addClickHandler(new SeriesClickHandler());
    }


    /**
     * Build a blank table with six rows.
     */
    private void buildBlankResultTable() {

        dicomTable.resize(9,6);
        String[] header = {"","Patient Name","Patient ID","Modality","Date Acquired","Date Added"};
        setHeaderRowData(header);

        String[] rowData = new String[]{"","","","",""};
        setRowStudyData(1,rowData);
        setRowStudyData(2,rowData);
        setRowStudyData(3,rowData);
        setRowStudyData(4,rowData);
        setRowStudyData(5,rowData);
        setRowStudyData(6,rowData);
        setRowStudyData(7,rowData);
        setRowStudyData(8,rowData);

        dicomTable.setStyleName(RESOURCE.dicomSearch().patientsTable());
        dicomTable.setWidth("100%");
        HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();
        rowFormatter.setStyleName(0,RESOURCE.dicomSearch().patientsTableHeaderRow());
    }

    /**
     *
     * @param data
     */
    public void setHeaderRowData(String[] data){

        HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();
        rowFormatter.setStyleName(0,RESOURCE.dicomSearch().patientsTableHeaderRow());

        String headerCell = RESOURCE.dicomSearch().patientsTableHeaderCell();
        HTMLTable.CellFormatter cellFormatter = dicomTable.getCellFormatter();

        for(int i=0;i<data.length;i++){
            dicomTable.setText(0,i,data[i]);
            cellFormatter.setStyleName(0,i,headerCell);
        }

    }

    /**
     * Putting some data into columns 1 to 5.
     * @param row
     * @param data
     */
    public void setRowStudyData(int row, String[] data){

        HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();

        String patientTableStudyRow = RESOURCE.dicomSearch().patientsTableStudyRow();
        String patientTableStudyRowEvent = RESOURCE.dicomSearch().patientsTableStudyRowEven();

        dicomTable.setHTML(row, 0, "<img src=\"./images/closed.png\" />");//closed
        for(int i=1;i<6;i++){
            dicomTable.setText(row,i,data[i-1]);
            rowFormatter.setStyleName(row,patientTableStudyRow);

            if( (row+1)%2==0 ){
                rowFormatter.addStyleName(row,patientTableStudyRowEvent);
            }
        }

        //make the first, and Modality columns centered.
        HTMLTable.ColumnFormatter colFormatter = dicomTable.getColumnFormatter();
        String centeredColumn = RESOURCE.dicomSearch().centeredColumn();
        colFormatter.addStyleName(0,centeredColumn);
        colFormatter.addStyleName(3,centeredColumn);

    }

    /**
     *
     * @param row
     * @param data
     */
    public void setRowStudyData(int row, Map<String,String> data){

        HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();

        String patientTableStudyRow = RESOURCE.dicomSearch().patientsTableStudyRow();
        String patientTableStudyRowEvent = RESOURCE.dicomSearch().patientsTableStudyRowEven();

        rowFormatter.setStyleName(row,patientTableStudyRow);
        if( (row+1)%2==0 ){
            rowFormatter.addStyleName(row,patientTableStudyRowEvent);
        }

        String studyUID = data.get("StudyUID");
        String patientName = data.get("Patient Name");
        String patientID = data.get("Patient ID");
        String examType = data.get("Exam Type");
        String dateAcquired = data.get("Date Acquired");

        rowFormatter.getElement(row).setAttribute(ATTR_STUDY_ID,studyUID);
        rowFormatter.getElement(row).setAttribute(ATTR_DICOM_TYPE,DT_STUDY);

        dicomTable.setHTML(row,0,"<img src=\"./images/closed.png\" "+ATTR_STUDY_ID+"=\""+studyUID+"\" />");
        dicomTable.setText(row, 1, patientName);
        dicomTable.setText(row,2,patientID);
        dicomTable.setText(row,3,examType);
        dicomTable.setText(row,4,dateAcquired);
        dicomTable.setText(row,5,dateAcquired);

        HTMLTable.CellFormatter cellFormatter = dicomTable.getCellFormatter();
        String centeredColumn = RESOURCE.dicomSearch().centeredColumn();
        String whiteCell = RESOURCE.dicomSearch().whiteCell();
        cellFormatter.addStyleName(row,0,centeredColumn);
        cellFormatter.addStyleName(row,0,whiteCell);
        cellFormatter.addStyleName(row,3,centeredColumn);
    }

    /**
     *
     * @param row
     * @param data
     */
    public void setRowSeriesData(int row, Map<String,String> data){

        int insertRow = row+1;

        dicomTable.insertRow(insertRow);
        HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();
        Element rowElement = rowFormatter.getElement(insertRow);

        //set the opacity to zero, populate it and fade it in.
        rowElement.getStyle().setDisplay(Style.Display.NONE);
        populateSeriesRow(data, insertRow, rowFormatter, rowElement);
        //$(rowElement).fadeIn(600);
        rowElement.getStyle().setOpacity(1.0);

    }

    private final void populateSeriesRow(Map<String, String> data, int insertRow, HTMLTable.RowFormatter rowFormatter, Element rowElement) {
        String seriesUID = data.get("Series Id");
        @SuppressWarnings("unused")
		String patientName = data.get("Patient Name");
        String patientID = data.get("Patient Id");
        String examType = data.get("Exam Type");
        String dateAcquired = data.get("Series Date");
        String seriesDesc = data.get("SeriesDescription");
        @SuppressWarnings("unused")
		String imagesInSeries = data.get("ImagesInSeries");
        String numImages = data.get("NumberOfSeriesRelatedInstances");
        String thumbnail = data.get("Thumbnail URL");

        dicomTable.setHTML(insertRow,0,"");
        dicomTable.setHTML(insertRow,1,"<span class=\"indent\">"+seriesDesc+"</span>"); //NOTE: need a series name.
        dicomTable.setText(insertRow,2,patientID);
        dicomTable.setText(insertRow,3,examType);
        dicomTable.setText(insertRow,4,dateAcquired);
        dicomTable.setText(insertRow,5,"# images: "+numImages);


        String seriesRow = RESOURCE.dicomSearch().patientsTableSeriesRow();
        rowFormatter.addStyleName(insertRow,seriesRow);


        rowElement.setAttribute(ATTR_DICOM_TYPE, DT_SERIES);
        rowElement.setAttribute(ATTR_SERIES_ID, seriesUID);
        rowElement.setAttribute(ATTR_THUMBNAIL, thumbnail);
        rowElement.setAttribute(ATTR_SERIES_DESC, seriesDesc);
        rowElement.setAttribute(ATTR_NUM_IMAGES, numImages);

        HTMLTable.CellFormatter cellFormatter = dicomTable.getCellFormatter();
        String centeredColumn = RESOURCE.dicomSearch().centeredColumn();
        cellFormatter.addStyleName(insertRow,3,centeredColumn);
    }

    /**
     * <img src="./images/closed.png" studyid="1.2.826.0.1.3680043.8.420.17864099421429702484295733867604129208">
     *
     * @param studyId
     */
    public void showSeriesDataForStudy(String studyId){
        int rowIndex = getRowIndexForStudy(studyId);
        dicomTable.setHTML(rowIndex,0,"<img src=\"./images/open.png\" />");
        //set studyid attribute
        HTMLTable.CellFormatter cellFormatter = dicomTable.getCellFormatter();
        cellFormatter.getElement(rowIndex,0).setAttribute(ATTR_STUDY_ID,studyId);
    }

    /**
     *
     *
     * @param studyId
     */
    public void hideSeriesDataForStudy(String studyId){
        try{

            int rowIndex = getRowIndexForStudy(studyId);

            dicomTable.setHTML(rowIndex,0,"<img src=\"./images/closed.png\" />");
            HTMLTable.RowFormatter rowFormatter = dicomTable.getRowFormatter();

            String type = rowFormatter.getElement(rowIndex+1).getAttribute(ATTR_DICOM_TYPE);
            while(DT_SERIES.equalsIgnoreCase(type)){
                //$(dicomTable.getRowFormatter().getElement(rowIndex+1)).f //hide.
                dicomTable.removeRow(rowIndex+1);
                type = rowFormatter.getElement(rowIndex+1).getAttribute(ATTR_DICOM_TYPE);
            }

        }catch(Exception e){
            //log.alert("hide series exception: "+e.getMessage()); //ToDo: remove when debug finished.
        }

    }


    public void resizeRows(int rows){
        dicomTable.resize(rows, NUM_COLUMNS);
    }

    /**
     *
     * @param studyId
     * @return
     */
    public int getRowIndexForStudy(String studyId){

        studyId=studyId.trim();

        int rowCount = dicomTable.getRowCount();
        for(int row=0;row<rowCount;row++){
            String currRowStudyId = dicomTable.getRowFormatter().getElement(row).getAttribute(ATTR_STUDY_ID);

            if( studyId.equalsIgnoreCase(currRowStudyId)){
                return row;
            }
        }
        //log.alert("Study not found: _"+studyId+"_"); //ToDo: Delete after debugging finished.
        return -1;
    }

    class SeriesClickHandler implements ClickHandler{

        /**
         *
         * @param clickEvent
         */
        @Override
        public void onClick(ClickEvent clickEvent) {
            try{

                HTMLTable.Cell cell = dicomTable.getCellForEvent(clickEvent);

                int row = cell.getRowIndex();
                int col = cell.getCellIndex();

                Element rowElement = dicomTable.getRowFormatter().getElement(row);
                String dicomType = rowElement.getAttribute(ATTR_DICOM_TYPE);

                //If this is column '0' and the row attribute dicomType="series";
                if( col==0 ){
                    if(DT_STUDY.equalsIgnoreCase(dicomType)){
                        String studyUID = rowElement.getAttribute(ATTR_STUDY_ID);
                        if(isStudyRowOpen(row)){
                            hideSeriesDataForStudy(studyUID);
                            //EventBus.fireEvent(new StudySelectEvent(studyUID,false));
                            return;
                        }
                        //EventBus.fireEvent(new StudySelectEvent(studyUID,true));
                        //String searchURL = SearchUtil.getBaseURL()+"/search/?searchtype=series&studyUID="+studyUID;
                        
                        //move this code to ImageListActivity
                        presenter.setThumbnail(studyUID);
                    
                    }else if( DT_SERIES.equalsIgnoreCase(dicomType)){
                        //log.alert("This appears to be a series row!!");
                    }
                }else if(col>0){
                    //If this study row is a study and it is open then load the thumbnails.
                    if( isStudyRow(row) && isStudyRowOpen(row) ){
                        //log.debug("Prepare LoadThumbnailsEvent for study row="+row);
                        @SuppressWarnings("unused")
						String studyUID = rowElement.getAttribute(ATTR_STUDY_ID);
                        //List<Thumbnail> thumbnailList = getThumnailsForStudy(row);
                        //EventBus.fireEvent( new LoadThumbnailsEvent(studyUID,thumbnailList));

                        //high-lite the row, and remove and remove style from all other rows.

                        String selectedRow = RESOURCE.dicomSearch().selectedStudyRow();
                        clearStudyRowOfCssClassName(selectedRow);
                        rowElement.addClassName(selectedRow);
                    }
                }

            }catch(Exception e){
                //log.alert(e.getMessage());
            }
        }//onClick

        /**
         * Goes through the entire patient table to clear the Study rows of CSS style.
         * @param cssClassName - name of the CSS class to remove from the Study row.
         */
        private void clearStudyRowOfCssClassName(String cssClassName){

            int rowCount = dicomTable.getRowCount();
            for(int i=0;i<rowCount;i++){
                if(isStudyRow(i)){
                    Element rowElement = dicomTable.getRowFormatter().getElement(i);
                    rowElement.removeClassName(cssClassName);
                }
            }
        }

        /**
         * Give this method a row, (it should be a "study"), and it will return
         * true if that row is "open" i.e. displays the series associated with it.
         * @param row
         * @return
         */
        private boolean isStudyRowOpen(int row){
            Element cellElement = dicomTable.getCellFormatter().getElement(row,0);
            String imageHTML = cellElement.getInnerHTML();
            return imageHTML.indexOf("open")>0;
        }

        /**
         * Check the current row to see if it is a DICOM Study row.
         * @param row
         * @return true if the row displays info about a Study.
         */
        private boolean isStudyRow(int row){
            Element rowElement = dicomTable.getRowFormatter().getElement(row);

            if(rowElement==null){
                return false;
            }
            String type = rowElement.getAttribute(ATTR_DICOM_TYPE);
            return DT_STUDY.equalsIgnoreCase(type);
        }

        /**
         * Get all the thumbnails for the series for this study by looking at the study.
         * @param row int row number of the study in the table.
         * @return
         */
        /*
        private List<Thumbnail> getThumnailsForStudy(int row){
            List<Thumbnail> retVal = new ArrayList<Thumbnail>();
            Element studyRowElement = dicomTable.getRowFormatter().getElement(row);
            assert studyRowElement.getAttribute(ATTR_STUDY_ID)!=null;

            int dataRowCount = dicomTable.getRowCount()-1;
            int currSeriesRow = row+1;
            while(currSeriesRow<dataRowCount){
                Element seriesRowElement = dicomTable.getRowFormatter().getElement(row);
                String seriesId = seriesRowElement.getAttribute(ATTR_SERIES_ID);
                if( seriesId==null ){
                    break;
                }
                String url = seriesRowElement.getAttribute(ATTR_THUMBNAIL);
                String desc = seriesRowElement.getAttribute(ATTR_SERIES_DESC);
                String numImages = seriesRowElement.getAttribute(ATTR_NUM_IMAGES);
                Thumbnail thumbnail = new Thumbnail(seriesId,url,desc,numImages);
                retVal.add(thumbnail);
                row++;
                if(isStudyRow(row)){
                    break;
                }
            }
            return retVal;
        }
		*/

    }//class SeriesClickHandler

    /**
     * Handles requests to get Series for a certain StudyUID.
     */
    class SeriesCallback implements RequestCallback {

        private final String studyId;

        public SeriesCallback(String studyUID){
            studyId = studyUID;
        }

        @Override
        public void onResponseReceived(Request request, Response response) {

            if( 200==response.getStatusCode()){
               String responseText = response.getText();

                if(!responseText.startsWith("Err")){
                    displayResult(responseText);
                }else{
                    //log.alert("----- Error -----\n"+responseText);
                }
            }else{
                //log.alert("Bad Response: "+response.getStatusCode());
            }

        }

        @Override
        public void onError(Request request, Throwable throwable) {
            //log.alert("SeriesCallback - error"+throwable.getMessage());
        }

        private void displayResult(String text){
            DicomResultModel.getInstance().parseSeriesResponse(text,studyId);
        }

    }//class SeriesCallback

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
		
	}

}
